#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <cstring>
#include <thread>

#include "EmotionFilter.h"
#include "myFilter.h"
#include "ColorfulLog.h"
// #define DEBUG



// 静态成员变量初始化
std::vector<PassFilterType> EmotionFilter::bandPassFilters(std::vector<PassFilterType>(64));
std::vector<NotchType> EmotionFilter::notch(std::vector<NotchType>(64));

/**********************************
 * 函数名：EmotionFilter::EmotionFilter
 * 功能：创建一个滤波器
 * 输入：滤波器参数文件名
 * 输出：无
 * 备注：从matlab生成滤波器，然后读滤波器参数
**********************************/
EmotionFilter::EmotionFilter(std::string filt_fileName)
:EmotionFilter(filt_fileName,0,0)
{
    // printf("default: GL_Cache=0, CL_Cache=0\n");
}

EmotionFilter::EmotionFilter(std::string filt_fileName, bool en_flag, bool refresh_flag)
    :m_cache("../Cache/eegFilter.cache",en_flag,refresh_flag)
{
    // 私有变量初始化
    filt_flag = true; 
    EmotionFiltParaMap["type"] = "0";
    EmotionFiltParaMap["order"] = "0.0";
    EmotionFiltParaMap["a"] = "0.0";
    EmotionFiltParaMap["b"] = "0.0";

    std::ifstream emotionFiltPara_fs(filt_fileName,std::ios::in);
    std::string line;
    if(!emotionFiltPara_fs.is_open()){
        LOG_ERR("file \"%s\" is not exit, open failed.\n",filt_fileName.c_str());
        #ifdef throw_error
        throw{
            "In ConfigImport::ConfigImport, EmotionFilterPara read fail."
        }

        #else
        filt_flag = false;
        #endif
    }

    // 获取文件头的标签
    while (getline(emotionFiltPara_fs,line)){
        std::istringstream iss(line);
        std::string file_flag,eq;
        // 解析文件
        // 去除行首尾的空白字符
        line.erase(0,line.find_first_not_of(" \t\n\r\f\v"));
        line.erase(line.find_last_not_of(" \t\n\r\f\v") + 1);
        // 跳过注释行
        if(!line.empty() && line[0] == '#'){
            continue;
        }

        if(!getline(iss,file_flag,'>')){
            continue;
        }
        // 去除符号<
        file_flag.erase(0,file_flag.find_first_not_of("<"));

        if(file_flag != (std::string)"Emotion filter"){
            LOG_ERR("filterFile type error, please check the file:[%s]\n",filt_fileName.c_str());
            #ifdef throw_error
            throw{
                "In ConfigImport::ConfigImport, EmotionFilterPara read fail."
            }
            #else
            filt_flag = false;
            #endif
        }
        else{
            break;
        }
    }

    // 获取滤波器参数
    while (getline(emotionFiltPara_fs,line)){
        std::istringstream iss(line);
        std::string key,val,eq;
        // 解析文件

        // 去除行首尾的空白字符
        line.erase(0,line.find_first_not_of(" \t\n\r\f\v"));
        line.erase(line.find_last_not_of(" \t\n\r\f\v") + 1);
        // 跳过注释行
        if(!line.empty() && line[0] == '#'){
            continue;
        }

        // 获取key
        if(!getline(iss,key,'=')){
            continue;
        }
        // 获取val
        if(!getline(iss,val)){
            continue;
        }
        // 删除key,val两端的空白字符,key.erase(position)方法会删除下标从position往后的所有
        key.erase(key.find_last_not_of(" \t\n\r\f\v") + 1);
        val.erase(0,val.find_first_not_of(" \t\n\r\f\v"));
        // val还要删掉有效值后面的" ;"
        val.erase(val.find(" ;"));

        if(EmotionFiltParaMap.find(key) == EmotionFiltParaMap.end()){
            printf("Extra parameter in config file, ignored.\n");
        }
        else{
            EmotionFiltParaMap[key] = val;
        }
    }
    emotionFiltPara_fs.close();

    // 解析参数
    // if(EmotionFiltParaMap.find("type") != EmotionFiltParaMap.end()){
    if(EmotionFiltParaMap["type"] == "filter"){
        filtType = 1;
    }
    else if(EmotionFiltParaMap["type"] == "filtfilt"){
        filtType = 2;
    }

    // order
    try{
        filtOrder = std::stoi(EmotionFiltParaMap["order"]);
    }

    catch (const std::invalid_argument& e) {
        LOG_ERR("字符串不能被转换为有效的数\n");
    }
    catch (const std::out_of_range& e) {
        LOG_ERR("转换的数字溢出\n");
    }

    // a
    filtA = new double[filtOrder+1];
    char* delim = (char*)" ";
    char* a = nullptr;
    filtA[0] = atof(strtok((char *)EmotionFiltParaMap["a"].c_str(),delim));
    for(int i = 1; i<filtOrder+1;++i){
        a = strtok(NULL,delim);
        if(a != nullptr){
            filtA[i] = atof(a);
        }
        else{
            filtA[i] = 0;
        }
    }

    // b
    filtB = new double[filtOrder+1];
    filtB[0] = atof(strtok((char *)EmotionFiltParaMap["b"].c_str(),delim));
    for(int i = 1; i<filtOrder+1;++i){
        a = strtok(NULL,delim);
        if(a != nullptr){
            filtB[i] = atof(a);
        }
        else{
            filtB[i] = 0;
        }
    }
    // 读滤波器参数
    // printf("filt initialization complete.\n");
    // filt_flag = true;

    // log
    if(en_flag){
        std::cout << "EmotionFilter cache enable, cache file: \"" << m_cache.get_cacheFile() << "\"" << std::endl;
    }
}

EmotionFilter::EmotionFilter(
                                // int order,
                                double fs,
                                double lowcut,
                                double highcut,
                                int channal_count,
                                double ripple_pass,
                                double ripple_stop
                                
)
    :m_cache("../Cache/eegFilter.cache",1,0)
{
    // 变量初始化
    // _order = FILTER_ORDER;
    _fs = fs;
    _lowcut = lowcut;
    _highcut = highcut;
    _ripple_pass = ripple_pass;
    _ripple_stop = ripple_stop;
    channalNum = channal_count;

    double centerFrequency = (_lowcut + _highcut) / 2.0;
    double widthFrequency = _highcut - _lowcut;

    // Create Elliptic bandpass filter for each channal
    for(int i=0; i<channalNum; ++i){
        bandPassFilters[i].setup(FILTER_ORDER, _fs, centerFrequency, widthFrequency);
        notch[i].setup(NOTCH_ORDER, _fs, 50, 5);
    }

}

EmotionFilter::~EmotionFilter()
{
    if(filtA != nullptr){
        delete[] filtA;
        filtA = nullptr;
    }
    if(filtB != nullptr){
        delete[] filtB;
        filtB = nullptr;
    }
}

void EmotionFilter::showMap(){
    printf("type:%s\n",EmotionFiltParaMap["type"].c_str());
    printf("order:%s\n",EmotionFiltParaMap["order"].c_str());

    // a
    printf("a:\n");
    for(int i=0; i<filtOrder+1; ++i){
        // std::cout << filtA[i] << std::endl;
        printf("%lf\n",filtA[i]);
    }

    // b
    printf("b:\n");
    for(int i=0; i<filtOrder+1; ++i){
        // std::cout << filtB[i] << std::endl;
        printf("%lf\n",filtB[i]);
    }

    // filtType
    printf("filtType:%d\n",filtType);

}

/**********************************
 * 函数名：EmotionFilter::filt
 * 功能：对输入的数据进行滤波
 * 输入：org_data: arma::mat类型的矩阵,存放滤波前的数据
 *      filt_data: arma::mat类型的矩阵,存放滤波后的数据
 * 输出：无
 * 备注：无
**********************************/
int EmotionFilter::filt(GenEEGData& org_data, GenEEGData& filt_data){
    // 先判断是否满足滤波条件
    if(!filt_flag){
        printf("Filter not activated...\n");
        return -1;
    }

    int my_Channel_Num = org_data.dataHead.channalNum;
    int testCount = org_data.data.size();
    double ** X = nullptr;
    X = new double* [my_Channel_Num];

    for(int ch_index=0; ch_index<my_Channel_Num; ++ch_index)
    {
        X[ch_index] = new double[testCount];//*usedTimes/(usedTimes*intervalTimes)];
        if(X[ch_index] == nullptr){
            printf("error\n");
            return -1;
        }
        std::memcpy(X[ch_index], org_data.data[ch_index].data(), testCount * sizeof(double));
        #ifdef DEBUG
        std::cout << "X[0]:" << std::endl;
        for (size_t i = 0; i < testCount; ++i) {
            std::cout << X[ch_index][i] << " ";
        }
        std::cout << std::endl;
        #endif // DEBUG
        
    }

    auto BT_filt = std::chrono::steady_clock::now();
    for(int ch_index=0; ch_index<my_Channel_Num; ++ch_index)
    {
        if(filtfilt(X[ch_index], X[ch_index], testCount, filtA, filtB, filtOrder+1)!=0)
        {
            printf_red("滤波器阶数过大或数据长度过短，将不进行滤波处理\n");
            // my_filt_flag = false;  //滤波失败将关闭滤波
            return -1;
        }
    }
    auto AT_filt = std::chrono::steady_clock::now();
    double duration_millsecond = std::chrono::duration<double, std::milli>(AT_filt - BT_filt).count();
    std::cout << "filt_times:" << duration_millsecond << "ms" << std::endl; 

    filt_data.dataHead.channalNum = my_Channel_Num;
    filt_data.data.clear();


    auto BT_cpy = std::chrono::steady_clock::now();
    for (int i = 0; i < testCount; ++i) {
        EEGDataArr temp = {0}; // 初始化 EEGDataArr
        for (int j = 0; j < my_Channel_Num; ++j) {
            // printf("i=%d,j=%d\n",i,j);
            temp[j] = X[j][i]; // 拷贝每一列的数据到 temp
        }
        filt_data.data.push_back(temp); // 将 temp 添加到 vector 中
    }
    auto AT_cpy = std::chrono::steady_clock::now();
    duration_millsecond = std::chrono::duration<double, std::milli>(AT_cpy - BT_cpy).count();
    std::cout << "cpy_times:" << duration_millsecond << "ms" << std::endl; 


    // filt_data.print("filt_data:");
    return 0;
}

int EmotionFilter::filt(arma::mat org_data, arma::mat& filt_data){
    // 先判断是否满足滤波条件
    if(!filt_flag){
        printf("Filter not activated...\n");
        return -1;
    }
    arma::mat _org = org_data;

    int my_Channel_Num = _org.n_rows;
    int testCount = _org.n_cols;
    double ** X = nullptr;
    X = new double* [my_Channel_Num];

    
    for(int ch_index=0; ch_index<my_Channel_Num; ++ch_index)
    {
        arma::rowvec n_row = _org.row(ch_index);
        X[ch_index] = new double[testCount];//*usedTimes/(usedTimes*intervalTimes)];
        if(X[ch_index] == nullptr){
            printf("error\n");
            return -1;
        }
        std::memcpy(X[ch_index], n_row.memptr(), n_row.n_elem * sizeof(double));

        #ifdef DEBUG
        std::cout << "X[0]:" << std::endl;
        for (size_t i = 0; i < n_row.n_elem; ++i) {
            std::cout << X[ch_index][i] << " ";
        }
        std::cout << std::endl;
        #endif // DEBUG
        
    }

    for(int ch_index=0; ch_index<my_Channel_Num; ++ch_index)
    {
        if(filtfilt(X[ch_index], X[ch_index], testCount, filtA, filtB, filtOrder+1)!=0)
        {
            printf_red("滤波器阶数过大或数据长度过短，将不进行滤波处理\n");
            // my_filt_flag = false;  //滤波失败将关闭滤波
            break;
        }
    }

    // arma::mat outMat(63,5000);
    // for(int ch_index=0; ch_index<my_Channel_Num; ++ch_index)
    // {
    //     for(int i=0; i<5000; ++i){
    //         outMat(ch_index,i) = X[ch_index][i];
    //     }
    //     // arma::rowvec n_row(5000);
    //     // std::memcpy(outMat.n_rows().memptr(), X[0][ch_index], 5000 * sizeof(double));
    //     // n_row.print();
    // }
    // outMat.print();

    for(int ch_index=0; ch_index<my_Channel_Num; ++ch_index)
    {
        filt_data.row(ch_index) = arma::rowvec(X[ch_index],filt_data.n_cols);
    }
    // filt_data.print();
    return 0;
}


/**********************************
 * 函数名：ellipticFilt
 * 功能：巴特沃斯滤波器
 * 输入：无
 * 输出：无
 * 备注：无
**********************************/
// 对一组通道进行滤波处理,滤波线程的任务函数
#define DEBUG
// #define FILT_TIME
void EmotionFilter::filterChannels(GenEEGData& org_data, GenEEGData& filt_data, int startIndex, int endIndex) {
    int pointNum = org_data.data.size();
    // std::cout << "pointNum:" << pointNum << std::endl;
    int filtChannalNum = endIndex - startIndex + 1;
    // std::cout << "filtChannalNum:" << filtChannalNum << std::endl;
    #ifdef FILT_TIME
    double duration_millsecond;
    #endif // FILT_TIME

    // 使用共享指针
    std::vector<std::shared_ptr<double[]>> inputPtr(filtChannalNum);
    // 提取裸指针数组
    std::vector<double*> rawPointers(filtChannalNum);
    for(int i=0; i<filtChannalNum; ++i){
        try{
            inputPtr[i] = (std::shared_ptr<double[]>(new double[pointNum]));
            rawPointers[i] = inputPtr[i].get();  // 获取裸指针
        }catch (const std::bad_alloc& e) {
            std::cerr << "Memory allocation failed for channel " << i << ": " << e.what() << std::endl;
            return;
        }
    }

    for (int channelIndex = startIndex; channelIndex <= endIndex; ++channelIndex) {
        int buf_channelIndex = 0;
        for(int i=0; i<pointNum; ++i){
            inputPtr[buf_channelIndex][i] = org_data.data[i][channelIndex];
        }

        #ifdef FILT_TIME
        auto BT_pass = std::chrono::steady_clock::now();
        #endif // FILT_TIME
        
        bandPassFilters[channelIndex].process(pointNum, rawPointers.data());
        notch[channelIndex].process(pointNum, rawPointers.data());

        #ifdef FILT_TIME
        auto AT_pass = std::chrono::steady_clock::now();
        duration_millsecond = std::chrono::duration<double, std::milli>(AT_pass - BT_pass).count();
        std::cout << "pass_times in one thread:" << duration_millsecond << "ms" << std::endl; 
        #endif // FILT_TIME
        
        for(int i=0; i<pointNum; ++i){
            filt_data.data[i][channelIndex] = inputPtr[buf_channelIndex][i];
        }

        ++buf_channelIndex;
    }

}

int EmotionFilter::ellipticFilt(GenEEGData& org_data, GenEEGData& filt_data){
    // Launch threads for parallel filtering
    std::vector<std::thread> threads;
    // 每个线程处理的通道数，四舍五入
    int channelsPerThread = channalNum / 4 + 0.5;
    int startIndex = 0;
    int endIndex = 0;

    while (startIndex < channalNum) {
        endIndex = ((startIndex + channelsPerThread -1) >= (channalNum-1)) ? (channalNum-1) : (startIndex + channelsPerThread -1);
        threads.emplace_back(filterChannels, std::ref(org_data), std::ref(filt_data), startIndex, endIndex);
        startIndex += channelsPerThread;
    }

    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    return 0;

}

int EmotionFilter::butterworthFilt(GenEEGData& org_data, GenEEGData& filt_data, uint8_t threadNum){
    std::vector<std::thread> threads;
    // 每个线程处理的通道数，四舍五入
    int channelsPerThread = (float)channalNum / threadNum + 0.5;
    int startIndex = 0;
    int endIndex = 0;


    while (startIndex < channalNum) {
        endIndex = ((startIndex + channelsPerThread -1) >= (channalNum-1)) ? (channalNum-1) : (startIndex + channelsPerThread -1);
        threads.emplace_back(filterChannels, std::ref(org_data), std::ref(filt_data), startIndex, endIndex);
        startIndex += channelsPerThread;
    }
    
    
    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }
    return 0;
}



bool EmotionFilter::save(arma::mat &data){
    return (m_cache.save(data));
}

bool EmotionFilter::load(arma::mat &data){
    return (m_cache.load(data));
}






